package com.lonely.purchase.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.page.Condition;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.order.service.IOrderPartMaterialService;
import com.lonely.purchase.domain.dto.remainingmaterialinventory.*;
import com.lonely.purchase.domain.entity.SysRemainingMaterialInventory;
import com.lonely.purchase.domain.entity.SysRemainingMaterialInventoryLog;
import com.lonely.purchase.domain.vo.remainingmaterialinventory.QueryRemainingMaterialInventoryPageVO;
import com.lonely.purchase.domain.vo.remainingmaterialinventory.QueryTypeInInventoryPageVO;
import com.lonely.purchase.domain.vo.remainingmaterialinventory.RemainingMaterialInventoryDetailVO;
import com.lonely.purchase.mapper.SysRemainingMaterialInventoryMapper;
import com.lonely.purchase.service.IRemainingMaterialInventoryLogService;
import com.lonely.purchase.service.IRemainingMaterialInventoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/7/25 16:18
 * @description: 物料库存服务实现类
 */
@Service
public class RemainingMaterialInventoryServiceImpl extends ServiceImpl<SysRemainingMaterialInventoryMapper, SysRemainingMaterialInventory> implements IRemainingMaterialInventoryService {

    @Autowired
    private IRemainingMaterialInventoryLogService remainingMaterialInventoryLogService;

    @Autowired
    private IOrderPartMaterialService orderPartMaterialService;

    /**
     * 余料库存分页查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<QueryRemainingMaterialInventoryPageVO> page(QueryRemainingMaterialInventoryPageDTO queryDto) {
        Page<QueryRemainingMaterialInventoryPageVO> page = Condition.page(queryDto);
        return super.getBaseMapper().page(page, queryDto);
    }

    /**
     * 批量删除
     *
     * @param batchRemoveDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchRemove(BatchRemoveRemainingMaterialInventoryDTO batchRemoveDto) {
        // 删除数据
        super.removeByIds(batchRemoveDto.getIds());

        // 记录日志
        List<SysRemainingMaterialInventoryLog> logs = batchRemoveDto.getIds().stream().map(x -> {
            SysRemainingMaterialInventoryLog remainingMaterialInventoryLog = new SysRemainingMaterialInventoryLog();
            remainingMaterialInventoryLog.setRemainingMaterialInventoryId(x);
            remainingMaterialInventoryLog.setLogTitle(String.format("%s删除余料库存", SecurityUtils.getUsername()));
            remainingMaterialInventoryLog.setLogBody(null);
            remainingMaterialInventoryLog.setCreateBy(SecurityUtils.getUserId());
            remainingMaterialInventoryLog.setUpdateBy(SecurityUtils.getUserId());
            return remainingMaterialInventoryLog;
        }).collect(Collectors.toList());
        this.remainingMaterialInventoryLogService.saveBatch(logs);
    }

    /**
     * 详情
     *
     * @param id
     * @return
     */
    @Override
    public RemainingMaterialInventoryDetailVO detail(Long id) {
        return super.getBaseMapper().getDetailById(id);
    }

    /**
     * 编辑余料库存
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(RemainingMaterialInventorySubmitDTO submitDto) {
        SysRemainingMaterialInventory remainingMaterialInventory = super.getById(submitDto.getId());
        Assert.notNull(remainingMaterialInventory, "余料库存不存在");
        RemainingMaterialInventoryDetailVO detail = this.detail(submitDto.getId());

        remainingMaterialInventory.setInventoryLocation(submitDto.getInventoryLocation());
        remainingMaterialInventory.setRemainingMaterialQuantity(Convert.toStr(submitDto.getRemainingMaterialQuantity()));
        remainingMaterialInventory.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(remainingMaterialInventory);

        // 添加操作日志
        SysRemainingMaterialInventoryLog remainingMaterialInventoryLog = new SysRemainingMaterialInventoryLog();
        remainingMaterialInventoryLog.setRemainingMaterialInventoryId(submitDto.getId());
        remainingMaterialInventoryLog.setLogTitle(String.format("%s更新库存为%s(%s)", SecurityUtils.getUsername(), submitDto.getRemainingMaterialQuantity(), detail.getUnit()));
        remainingMaterialInventoryLog.setLogBody(null);
        remainingMaterialInventoryLog.setCreateBy(SecurityUtils.getUserId());
        remainingMaterialInventoryLog.setUpdateBy(SecurityUtils.getUserId());
        this.remainingMaterialInventoryLogService.save(remainingMaterialInventoryLog);
    }

    /**
     * 录入库存时物料库存分页列表
     *
     * @param pageDto
     * @return
     */
    @Override
    public Page<QueryTypeInInventoryPageVO> queryTypeInMaterialInventoryPage(QueryTypeInMaterialInventoryPageDTO pageDto) {
        Page<RemainingMaterialInventoryDetailVO> page = Condition.page(pageDto);
        return super.getBaseMapper().queryTypeInMaterialInventoryPage(page, pageDto);
    }

    /**
     * 录入库存
     *
     * @param typeInInventorys
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void typeInRemainingMaterialInventory(List<TypeInMaterialInventorySubmitDTO> typeInInventorys) {
        if (CollUtil.isEmpty(typeInInventorys)) {
            return;
        }

        // 找到待新增的数据
        List<TypeInMaterialInventorySubmitDTO> needAddInventorys = typeInInventorys.stream().filter(x -> x.getRemainingMaterialInventoryId() == null).collect(Collectors.toList());

        // 找到待编辑的数据
        List<TypeInMaterialInventorySubmitDTO> needUpdateInventorys = typeInInventorys.stream().filter(x -> x.getRemainingMaterialInventoryId() != null).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(needUpdateInventorys)) {
            // 提交的库存数量映射
            Map<Long, TypeInMaterialInventorySubmitDTO> newInventoryQuantityMap = needUpdateInventorys.stream().collect(Collectors.toMap(TypeInMaterialInventorySubmitDTO::getRemainingMaterialInventoryId, Function.identity(), (x, y) -> x));

            // 获取数据库中已有的数据
            List<SysRemainingMaterialInventory> oldInventorys = super.listByIds(needUpdateInventorys.stream().map(TypeInMaterialInventorySubmitDTO::getRemainingMaterialInventoryId).distinct().collect(Collectors.toList()));
            List<SysRemainingMaterialInventory> needUpdateDatas = oldInventorys.stream()
                    // 后续看是否添加该判断，该判断是如果数量没有改变，则不处理，但是现在加入了库存地址，所以待后续需求决定是否需要添加该过滤
                    //.filter(x -> !Objects.equals(x.getRemainingMaterialQuantity(), Convert.toStr(newInventoryQuantityMap.get(x.getId()).getTypeInMaterialQuantity())))
                    .peek(x -> {
                        x.setRemainingMaterialQuantity(Convert.toStr(newInventoryQuantityMap.get(x.getId()).getTypeInMaterialQuantity()));
                        x.setInventoryLocation(newInventoryQuantityMap.get(x.getId()).getInventoryLocation());
                        x.setUpdateBy(SecurityUtils.getUserId());
                    }).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(needUpdateDatas)) {
                super.updateBatchById(needUpdateDatas);

                // 添加日志
                List<SysRemainingMaterialInventoryLog> logs = needUpdateDatas.stream().map(x -> {
                    SysRemainingMaterialInventoryLog remainingMaterialInventoryLog = new SysRemainingMaterialInventoryLog();
                    remainingMaterialInventoryLog.setRemainingMaterialInventoryId(x.getId());
                    remainingMaterialInventoryLog.setLogTitle(String.format("%s更新库存为%s(%s)", SecurityUtils.getUsername(), x.getRemainingMaterialQuantity(), newInventoryQuantityMap.get(x.getId()).getUnit()));
                    remainingMaterialInventoryLog.setLogBody(null);
                    remainingMaterialInventoryLog.setCreateBy(SecurityUtils.getUserId());
                    remainingMaterialInventoryLog.setUpdateBy(SecurityUtils.getUserId());
                    return remainingMaterialInventoryLog;
                }).collect(Collectors.toList());
                this.remainingMaterialInventoryLogService.saveBatch(logs);
            }
        }

        // 待新增的数据处理
        if (CollUtil.isNotEmpty(needAddInventorys)) {

            List<SysRemainingMaterialInventory> needAddData = needAddInventorys.stream().map(x -> {
                SysRemainingMaterialInventory inventory = new SysRemainingMaterialInventory();
                inventory.setMaterialSku(x.getMaterialSku());
                inventory.setRemainingMaterialQuantity(Convert.toStr(x.getTypeInMaterialQuantity()));
                inventory.setInventoryLocation(x.getInventoryLocation());
                inventory.setCreateBy(SecurityUtils.getUserId());
                inventory.setUpdateBy(SecurityUtils.getUserId());
                return inventory;
            }).collect(Collectors.toList());
            super.saveBatch(needAddData);

            Map<String, String> materialItemUnitMap = needAddInventorys.stream().collect(Collectors.toMap(TypeInMaterialInventorySubmitDTO::getMaterialSku, TypeInMaterialInventorySubmitDTO::getUnit));
            this.remainingMaterialInventoryLogService.saveBatch(needAddData.stream().map(x -> {
                SysRemainingMaterialInventoryLog remainingMaterialInventoryLog = new SysRemainingMaterialInventoryLog();
                remainingMaterialInventoryLog.setRemainingMaterialInventoryId(x.getId());
                remainingMaterialInventoryLog.setLogTitle(String.format("%s新增库存为%s(%s)", SecurityUtils.getUsername(), x.getRemainingMaterialQuantity(), materialItemUnitMap.get(x.getMaterialSku())));
                remainingMaterialInventoryLog.setLogBody(null);
                remainingMaterialInventoryLog.setCreateBy(SecurityUtils.getUserId());
                remainingMaterialInventoryLog.setUpdateBy(SecurityUtils.getUserId());
                return remainingMaterialInventoryLog;
            }).collect(Collectors.toList()));
        }
    }

}
